package com.googlecode.wheres_my_stuff_okay_potato;

import java.io.Serializable;
import java.util.LinkedList;
import java.util.List;

import android.util.Log;

/**
 * Represents a user in this program. Each user is a profile that contains a
 * username, a password, an email address, and a list of associated items. In
 * addition, a user's account can be locked and unlocked.
 * 
 * @author Jeremy Hehn
 */
public class User implements Serializable {
	private static final long serialVersionUID = -9027725032267488485L;
	private static final String USER_TAG = "user";
	protected final String username;
	protected String password, email;
	protected boolean locked;
	private List<Item> items;

	/**
	 * Creates a user with a specified username, password, and email address.
	 * 
	 * @param username
	 *            is the user's username.
	 * @param password
	 *            is the user's password.
	 * @param email
	 *            is the user's email address.
	 */
	public User(String username, String password, String email) {
		this.username = username;
		this.password = password;
		this.email = email;

		items = new LinkedList<Item>();
		locked = false;
	}

	/**
	 * Attempts to log the user into the WMS system.
	 * 
	 * @param password
	 *            is the password to be used.
	 * @return true if the user was logged in.
	 * @throws WrongPasswordException
	 *             if the wrong password is entered.
	 * @throws LockedException
	 *             if the user is locked.
	 */
	public boolean attemptLogin(String password) throws WrongPasswordException,
			LockedException {
		if (!password.equals(this.password)) {
			Log.d(USER_TAG, password + " is not " + this.password);
			throw new WrongPasswordException();
		} else if (locked)
			throw new LockedException();
		else
			return true;
	}

	/**
	 * Returns the username of this user.
	 * 
	 * @return the username of this user.
	 */
	public String getUsername() {
		return username;
	}

	/**
	 * Sets the password for this user.
	 * 
	 * @param password
	 *            is the password this user should use to log in.
	 */
	public void setPassword(String password) {
		this.password = password;
	}

	/**
	 * Checks if the user's account is locked.
	 * 
	 * @return true if the user's account is locked; false otherwise.
	 */
	public boolean isLocked() {
		return locked;
	}

	/**
	 * Locks the user's account.
	 * 
	 * @return true if the user's account was locked; false otherwise.
	 */
	public boolean lock() {
		if (!isLocked())
			locked = true;

		return locked;
	}

	/**
	 * Unlocks the user's account.
	 */
	protected void unlock() {
		locked = false;
	}

	/**
	 * Returns the list of items associated with this user.
	 * 
	 * @return the list of items associated with this user.
	 */
	public List<Item> getItems() {
		return items;
	}

	/**
	 * Adds an item to this user's list of items.
	 * 
	 * @param item
	 *            is the item to be added to this user's list of items.
	 * @return true if the item was added; false otherwise.
	 */
	public boolean addItem(Item item) {
		return items.add(item);
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((email == null) ? 0 : email.hashCode());
		// result = prime * result + ((items == null) ? 0 : items.hashCode());
		result = prime * result + (locked ? 1231 : 1237);
		result = prime * result
				+ ((password == null) ? 0 : password.hashCode());
		result = prime * result
				+ ((username == null) ? 0 : username.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object other) {
		User otherUser = (User) other;
		return otherUser.getUsername().equals(this.username);
	}

	/**
	 * This method is overridden by the Admin subclass.
	 * 
	 * @return false every time.
	 */
	public boolean isAdmin() {
		return false;
	}

	/**
	 * Simple exception subclass thrown when an incorrect password is supplied
	 * for a user.
	 * 
	 * @author Jeremy Hehn
	 */
	public class WrongPasswordException extends Exception {
		private static final long serialVersionUID = -246795774008053948L;

		/**
		 * Creates a new WrongPasswordException.
		 */
		public WrongPasswordException() {
			super();
		}

		/**
		 * Creates a new WrongPasswordException with a specified message.
		 * 
		 * @param message
		 *            is the message that this WrongPasswordException should
		 *            display when it is thrown.
		 */
		public WrongPasswordException(String message) {
			super(message);
		}
	}

	/**
	 * Simple exception subclass thrown when a user's account is locked.
	 * 
	 * @author Jeremy Hehn
	 */
	public class LockedException extends Exception {
		private static final long serialVersionUID = 4438706438094444139L;

		/**
		 * Creates a new LockedException.
		 */
		public LockedException() {
			super();
		}

		/**
		 * Creates a new LockedException with a specified message.
		 * 
		 * @param message
		 *            is the error message that should be displayed when this
		 *            exception is thrown.
		 */
		public LockedException(String message) {
			super(message);
		}
	}
}